using System;
using System.Collections.Generic;
using System.Text;

namespace Chan_cli.Modules
{

    // Exceptions! ^^
    class CategoryAlreadyExistsException : Exception
    {
        public CategoryAlreadyExistsException() {}
        public CategoryAlreadyExistsException(string message) : base(message) { }
    }
    class CategoryDoesNotExistException : Exception
    {
        public CategoryDoesNotExistException() { }
        public CategoryDoesNotExistException(string message) : base(message) { }
    }
    class LinkAlreadyExistsException : Exception
    {
        public LinkAlreadyExistsException() { }
        public LinkAlreadyExistsException(string message) : base(message) { }
    }
    class LinkDoesNotExistException : Exception
    {
        public LinkDoesNotExistException() { }
        public LinkDoesNotExistException(string message) : base(message) { }
    }

    // Helper classes...
    class SidebarCategory
    {
        
        // Variables
        public string Name;
        public bool Collapsed; // Actual collpasing will be done by Javascript; we can save this setting with AJAX ^^
        public bool Visible;

        // This cannot be set by constructor
        public Dictionary<string, SidebarLink> Links;

        // Constructor
        public SidebarCategory(string _Name, bool _Collapsed, bool _Visible)
        {
            
            // Variables
            Name = _Name;
            Collapsed = _Collapsed;
            Visible = _Visible;
            Links = new Dictionary<string, SidebarLink>();

        }

        // Add Link
        public void AddLink(string ID, string Text, string URL, bool Visible)
        {

            // Exist?
            if (Links.ContainsKey(ID))
                throw new LinkAlreadyExistsException("Cannot add link '" + ID + "' to category '" + Name + " of sidebar because it already exists.");
            else
                Links.Add(ID, new SidebarLink(Text, URL, Visible));

        }

        // Delete Link
        public void DeleteLink(string ID)
        {

            // Exist?
            if (Links.ContainsKey(ID))
                Links.Remove(ID);
            else
                throw new LinkDoesNotExistException("Cannot delete link '" + ID + "' from categeory '" + Name + "' of sidebar because link does not exist.");

        }

        // Get Link
        public SidebarLink GetLink(string ID)
        {
            
            // Exist?
            if (Links.ContainsKey(ID))
                return Links[ID];
            else
                throw new LinkDoesNotExistException("Cannot get link '" + ID + "' from category '" + Name + "' of sideba because link does not exist.");

        }

        // Set Link
        public void SetLink(string ID, SidebarLink Link)
        {

            // Does it exist?
            if (Links.ContainsKey(ID))
                Links[ID] = Link;
            else
                // Instead of erroring, we'll add ^^
                Links.Add(ID, Link);

        }

    }
    struct SidebarLink
    {

        // Vars
        public string Text;
        public string URL;
        public bool Visible;

        // Constructor
        public SidebarLink(string _Text, string _URL, bool _Visible)
        {
            Text = _Text;
            URL = _URL;
            Visible = _Visible;
        }

    }

    // The big cheese!
    class SidebarModule : Module
    {

        // Variables
        Dictionary<string, SidebarCategory> Categories;
        string LinkTarget;

        // Constructor
        public SidebarModule(string Target)
        {

            LinkTarget = Target;
            Categories = new Dictionary<string, SidebarCategory>();

        }

        // Add Category
        public void AddCategory(string Name, SidebarCategory Category)
        {

            // Does it already exist?
            if (Categories.ContainsKey(Name))
                throw new CategoryAlreadyExistsException("Category '" + Name + "' already exists when trying to add to sidebar.");
            else
                 // Add
                Categories.Add(Name, Category);

        }
        
        // Delete Category
        public void DeleteCategory(string Name)
        {

            // Does it exist?
            if (Categories.ContainsKey(Name))
                Categories.Remove(Name);
            else
                throw new CategoryDoesNotExistException("Could not delete category '" + Name + "' from the sidebar because it doesn't exist.");

        }

        // Post request -- Generate HTMLz!
        public override byte[] Request(string[] Path)
        {

            // We'll ignore path; no point! :)

            // Start HTMLness!
            string HTML = string.Empty;
            HTML += "<html>\r\n";
            HTML += "<head>\r\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"/files/theme/sidebar.css\"/>\r\n\t<script type=\"text/javascript\" src=\"/files/sidebar/javascript.js\"></script>\r\n</head>\r\n";
            HTML += "<body>\r\n";
            HTML += "\t<h1>notp2pchan</h1><p class=\"text\">I think alittle bit of text about our project should go here. Keep it brief. ^^.</p>\r\n\r\n";
        
            // For each catgeory...
            foreach (SidebarCategory Cat in Categories.Values)
            {

                // Visible?
                if (Cat.Visible)
                {

                    // Title!
                    HTML += "\t<a href=\"#\" OnClick=\"Toggle('cat" + Cat.Name + "', 'cat" + Cat.Name + "Title');\">" + "<div class=\"heading\" id=\"cat" + Cat.Name + "Title\">Boards</div></a>\r\n";
                    HTML += "\t\t<ul id=\"cat" + Cat.Name + "\" class=\"category\" style=\"display: " + (Cat.Collapsed ? "none" : "") + "\">\r\n";

                    // For each Link
                    foreach (SidebarLink Link in Cat.Links.Values)
                        if (Link.Visible)
                            HTML += "\t\t\t<li class=\"link\"><a href=\"" + Link.URL + "\" target=\"" + LinkTarget + "\">" + Link.Text + "</a></li>\r\n";

                    // End List
                    HTML += "\t\t</ul>\r\n";
                    HTML += "\t\r\n\r\n";

                }

            }

            // End HTMLness!
            HTML += "</body>\r\n";
            HTML += "</html>\r\n";

            return ASCIIEncoding.ASCII.GetBytes(HTML);
        
        }
        
        // Page exist?
        public override bool PathExist(string[] Path)
        {
        	// Ignore path, it'll always exist.
        	return true;
        }

		// Request with data
		public override byte[] RequestData(string[] Path, POSTData[] Data)
		{
		
			// We can't be affected by data etc.
			return Request(Path);
		
		}

    }
}
